
#include <iostream>

// for string to argv
#include <string>

#ifdef __cplusplus
extern "C"{
#endif

// C code...
// for string to argv
#include "cmd2argv.h"

#ifdef __cplusplus
}
#endif

#include "util.hxx"
#include "minilog_static.hxx"
#include "module.hxx"
#include "modules.hxx"

#include "thread_pool.hxx"

using std::string;

using std::pair;
using std::cout;
using std::endl;

struct moduleRespond* TestModulesManager::makeSingleAck(struct moduleRequest *request,
                                                        void *data, int size)
{
    struct moduleRespond*res = new struct moduleRespond;

    if(!res) return nullptr;

    res->type = RespondTypeModuleResult;
    res->data = data;
    res->size = size;
    return res;
}

struct moduleRespond* TestModulesManager::makeDataAck(const string &module)
{
    struct moduleRespond*res = new struct moduleRespond;

    if(!res) return nullptr;

    res->type = RespondTypeModuleResultData;
    res->data = this->getModulePendingDataByName(module);
    res->size = MODULE_DATA_MAX_SIZE;
    return res;
}

struct moduleRespond* TestModulesManager::handleRequestTypeGetStatusOfAllModulesWithCount(void)
{
    struct moduleRespond* res = new struct moduleRespond;

    if(!res) return nullptr;

    res->type = RespondTypeModuleResultsForGetStatusOfAllModulesWithCount;
    res->data = this->getModulesResults();
    res->size = this->getCountOfAllModules() * (sizeof(struct moduleResult));

    return res;
}

// 处理外部请求，返回对应的数据
// 注意，返回值(struct moduleRespond *)需要自行释放
struct moduleRespond *TestModulesManager::handleRequest(struct moduleRequest *request)
{
    int ret, size;
    void *data;
    string module;
    struct moduleRuntimeArg * runtimeArg = nullptr;
    if(!request) return nullptr;

    module = string(request->name);
    // 默认，但可能会被case改变
    size = sizeof(ret);
    data = &ret;

    switch (request->type) {
        // 获取执行结果
        case RequestTypeGetCommandResult:
            ret = this->getModuleResult(module);
            goto singleAck;
        // 获取所有模块数量:
        case RequestTypeGetCountOfAllModules:
            ret = this->getCountOfAllModules();
            goto singleAck;
        // 获取所有模块执行结果（要求先获取对应的数量）:
        case RequestTypeGetStatusOfAllModulesWithCount:
            goto messAck;
        // 指定执行结果
        case RequestTypeSetCommandResult:
            ret = this->setModuleResult(module, request->result);
            goto singleAck;
        // 执行模块
        case RequestTypeRunCommand:
            if(request->dataSize != 0)
            {
                runtimeArg = TestModule::newRuntimeArgFromRequest(request);
            }
            if(module == "all")
            {
                // 暂不支持所有模块使用同一个参数运行（runtimeArg需异步delete）
                ret = this->execAllModules(ModuleExecAllType);
                goto singleAck;
            }
            ret = this->execModuleWithRuntimeArg(module, runtimeArg);
            goto singleAck;
        // 获取模块执行时数据
        case RequestTypeGetPendingData:
            goto dataAck;
        default:
            LogE("unknow type!");
            goto nop;
    }

singleAck:
    return makeSingleAck(request,
                         data, size);
dataAck:
    return makeDataAck(module);
messAck:
    return handleRequestTypeGetStatusOfAllModulesWithCount();
nop:
    return nullptr;
}


int strs2moduleRequest(const string & run_mode, const string & cmd, const string & set_value,
                       struct moduleRequest *request)
{
    if(!request) return -1;
    // 默认
    request->requestMagic = REQUEST_MAGIC;
    request->type = RequestTypeUnknow;
    if(run_mode == "run" || run_mode == "r")
    {
        request->type = RequestTypeRunCommand;
        request->dataSize = min(set_value.length() + 1, REQUEST_MAX_DATA_SIZE);
        memcpy(request->data, (char*)set_value.c_str(), request->dataSize);
        request->data[request->dataSize] = '\0';
    }else if(run_mode == "set" || run_mode == "s")
    {
        request->type = RequestTypeSetCommandResult;
        if(set_value == "ok")
        {
            request->result = TestResultAsPass;
        }else
        {
            request->result = TestResultAsFail;
        }
    }else if(run_mode == "get" || run_mode == "g")
    {
         if(cmd == "all")
        {
            request->type = RequestTypeGetStatusOfAllModulesWithCount;
        } else if(set_value == "")
        {
            request->type = RequestTypeGetCommandResult;
        } else if(set_value == "pending")
        {
            request->type = RequestTypeGetPendingData;
        }
    }

    //request->dataSize = min(cmd.length() + 1, REQUEST_MAX_DATA_SIZE);
    memcpy(request->name, (char*)cmd.c_str(), MODULE_NAME_MAX_SIZE);
    request->name[MODULE_NAME_MAX_SIZE - 1] = '\0';

    return 0;
}

int cargv2moduleRequest(int argc, char *argv[], struct moduleRequest *request)
{
    std::string run_mode, cmd, set_value;

    if(!request) return -1;

    if(parseCarg(argc, argv, run_mode, cmd, set_value))
    {
        LogE(__FILE__, __LINE__, "error when parseCarg");
        return -1;
    }

    return strs2moduleRequest(run_mode, cmd, set_value, request);
}

// 将字符串转换为请求
int str2moduleRequest(const string &requestStr, struct moduleRequest *request)
{
    int ret;
    char **argv = nullptr;
    size_t argc = 0;

    if(!request) return -1;

    if (cmd2argv_malloc(requestStr.c_str(), &argv, &argc, NULL) != C2A_OK)
    {
        return -1;
    }
    if(argc) argc--;

    ret = cargv2moduleRequest(argc, argv, request);

    cmd2argv_free(argv);

    return ret;
}

// 注意，返回值(struct moduleRespond *)需要自行释放
struct moduleRespond *TestModulesManager::handleRequest(const string &requestStr)
{
    struct moduleRequest request;
    if(str2moduleRequest(requestStr, &request))
        return nullptr;

    return  this->handleRequest(&request);
}

// 注意，返回值(struct moduleRespond *)需要自行释放
struct moduleRespond *TestModulesManager::handleRequest(int argc, char * argv[])
{
    struct moduleRequest request;
    if(cargv2moduleRequest(argc, argv, &request))
        return nullptr;
    return  this->handleRequest(&request);
}

void TestModulesManager::insertModule(class TestModule* module, void* arg)
{
    if(!module)
    {
        LogE(__FILE__, __LINE__, "insertModule but null!");
        return;
    }

    if(findModule(module->getName()) != nullptr)
    {
        LogE(__FILE__, __LINE__, "existed!");
        return;
    }

    m_modulesMap.insert(pair <string, TestModule*> (module->getName(), module));
    module->setOwner(this);
    if(arg) module->setActionArg(arg);
    module->preInit();
}

void TestModulesManager::insertModules(class TestModule* moduleList[], void* arg)
{
    class TestModule* p = moduleList[0];
    while(p != nullptr)
    {
        insertModule(p, arg);
        p++;
    }
}

// 通过结构体构造模块类
void TestModulesManager::insertModules(struct TestModuleSt* moduleList, void* arg)
{
    struct TestModuleSt* p = moduleList;
    class TestModule* m;

    int i = 0;
    while(&p[i] != nullptr)
    {
        if(p[i].name == "") break;
        LogI("insertModule :", p[i].name);
        m = new class TestModule(p[i].name,
                                 p[i].defaultResult,
                                 p[i].moduleEnable,
                                 p[i].autoEnable);
        m->setActions(p[i].preInit,
                      p[i].init,
                      p[i].run,
                      p[i].quit,
                      p[i].getPendingData,
                      p[i].action_notify);
        insertModule(m, p[i].arg);
        i++;
    }
}

#if 0
void TestModulesManager::insertModulesByMethodList(struct moduleMAList *methodArray)
{
    class TestModule* p;
    struct moduleMAList *cur = &methodArray[0];
    void *arg;

    while(cur->method)
    {
        p   = cur->method();
        arg = cur->arg;

        LogI(__FILE__, __LINE__, "adding [", p->getName(), "]");

        insertModule(p, arg);
        cur++;
    }
}
#endif

class TestModule* TestModulesManager::findModule(const string &name)
{
    class TestModule* module = nullptr;
    map<string, TestModule* > ::iterator l_it;

    l_it = m_modulesMap.find(name);
    if(l_it == m_modulesMap.end())
    {
        LogI(__FILE__, __LINE__, "findModule : ", name ," not found ");
        return nullptr;
    }

    //cout<<"find " << name<<endl;
    LogI(__FILE__, __LINE__, "findModule : ", name);
    module = m_modulesMap[name];
    return module;
}

void TestModulesManager::setModuleRuntimeArg(class TestModule* module, struct moduleRuntimeArg * runtimeArg)
{
    if(!module) return ;
    module->setRuntimeArg(runtimeArg);
}

bool TestModulesManager::execModuleByName(const string &name)
{
    class TestModule* module = nullptr;

    module = findModule(name);
    if(!module) return -1;

    return fullRunModule(module);
}

bool TestModulesManager::execModuleWithRuntimeArg(const string &moduleName,
                                                  struct moduleRuntimeArg * runtimeArg)
{
    class TestModule* module = nullptr;

    module = findModule(moduleName);
    if(!module) return -1;
    setModuleRuntimeArg(module, runtimeArg);

    return fullRunModule(module);
}


char* TestModulesManager::getModulePendingDataByName(const string &name)
{
    class TestModule* module = nullptr;

    module = findModule(name);
    if(!module) return nullptr;

    return module->getPendingData();
}

// 执行注册的模块， execType 决定了执行测试单元的数量
bool TestModulesManager::execAllModules(enum ModuleExecType execType,
                                        struct moduleRuntimeArg * runtimeArg)
{
    class TestModule* module = nullptr;
    //string moduleName;
    bool ret = -1;

    map<string, TestModule*> ::iterator l_it;
    map<string, TestModule*> ::iterator l_itEnd;

    /* 需要考虑多线程的内存泄漏，暂不支持 */
    if(runtimeArg)
        delete runtimeArg;

    // execType TODO, full run for now.

    l_it    = m_modulesMap.begin();
    l_itEnd = m_modulesMap.end();

    while (l_it != l_itEnd) {
        //moduleName = l_it->first;
        module      = l_it->second;
        module->setRuntimeArg(runtimeArg);
        ret = fullRunModule(module);
        l_it++;
    }

    return ret;
}

bool TestModulesManager::getModuleResult(const string &moduleName)
{
    class TestModule* module = findModule(moduleName);
    if(!module) return -1;
    return module->getRunResult();
}

bool TestModulesManager::setModuleResult(const string &moduleName, bool result)
{
    class TestModule* module = findModule(moduleName);
    if(!module) return -1;
    module->setRunResult(result);
    return 0;
}

// 动态查询每一个模块的结果，并把结果储存下来
struct moduleResult * TestModulesManager::getModulesResults(void)
{
    int cnt, i;
    class TestModule* module = nullptr;

    map<string, TestModule*> ::iterator l_it;
    map<string, TestModule*> ::iterator l_itEnd;

    cnt = getCountOfAllModules();

    // re-malloc
    if(m_moduleResult) delete []m_moduleResult;
    m_moduleResult = new struct moduleResult[cnt];

    l_it    = m_modulesMap.begin();
    l_itEnd = m_modulesMap.end();
    i       = 0;

    while (l_it != l_itEnd) {
        module      = l_it->second;

        memcpy(m_moduleResult[i].name, (char*)module->getName().c_str(), MODULE_NAME_MAX_SIZE);
        m_moduleResult[i].result = module->getRunResult();
        LogI("getModulesResults :", module->getName(), ":", module->getRunResult());
        l_it++;
        i++;
    }

    return m_moduleResult;
}

// 获取当前注册的模块数量
int TestModulesManager::getCountOfAllModules(void)
{
    int cnt = 0;

    map<string, TestModule*> ::iterator l_it;
    map<string, TestModule*> ::iterator l_itEnd;

    l_it    = m_modulesMap.begin();
    l_itEnd = m_modulesMap.end();

    while (l_it != l_itEnd) {
        cnt++;
        l_it++;
    }

    return cnt;
}

// 内部函数：完整地执行功能模块
static void thread_fullRunModule(thread_context_t *thread_ctx)
{
    //class TestModulesManager* moduleManager;
    bool ret = -1;
    class TestModule* module = (class TestModule*)thread_ctx->task->argument;

    if(!module) return;

    //moduleManager = module->getOwner();

    //LogI(__FILE__, __LINE__, "thread_fullRunModule, task flag : ", thread_ctx->task->flags);
    LogI(__FILE__, __LINE__, module->getName());

    ret = module->init();
    if(ret)    goto quit;

    ret = module->run();
    LogI(__FILE__, __LINE__, module->getName(), "->run :", ret);
    // for debug
    // moduleManager->getModulesResults();
quit:
    module->quit();
}

// 以线程的形式执行
bool TestModulesManager::fullRunModule(class TestModule* module)
{
    return m_pool->addTask(thread_fullRunModule, module);
}

TestModulesManager::TestModulesManager(void)
{
    m_moduleResult = nullptr;
    m_pool = new class threadPool(20, 64);
}

TestModulesManager::~TestModulesManager(void)
{
    if(m_moduleResult) delete m_moduleResult;
    m_moduleResult = nullptr;

    delete m_pool;
}
